package xyz.tanxiao.links.controller;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import xyz.tanxiao.links.common.entity.PasswordAccessRequest;
import xyz.tanxiao.links.common.entity.ResponseResult;
import xyz.tanxiao.links.common.enums.LimitTargetEnum;
import xyz.tanxiao.links.common.exception.PasswordAccessException;
import xyz.tanxiao.links.common.utils.ValidationUtils;
import xyz.tanxiao.links.core.limit.SimpleAccessLimit;
import xyz.tanxiao.links.core.limit.SimpleAccessLimits;
import xyz.tanxiao.links.entity.SlLinkMapping;
import xyz.tanxiao.links.service.SlLinkAccessService;

import java.util.concurrent.TimeUnit;


/**
 * 短链访问控制器
 *
 * @author 万成波
 * @email 2300064869@qq.com
 * @createTime 2023-06-11 04:17:03 星期日
 */
@Slf4j
@RequiredArgsConstructor
@Controller
public class LinkAccessController {

	private final SlLinkAccessService linkAccessService;


	/**
	 * 普通访问短链接，302重定向到原始长链接。
	 *
	 * @param mappingKey 长链接映射Key
	 * @return 长链接地址
	 */
	@SimpleAccessLimits({
		@SimpleAccessLimit(target = LimitTargetEnum.GENERAL_ACCESS, level = 1, time = 5, timeUnit = TimeUnit.SECONDS, count = 3),
		@SimpleAccessLimit(target = LimitTargetEnum.GENERAL_ACCESS, level = 2, timeUnit = TimeUnit.MINUTES, count = 15)
	})
	@ResponseStatus(HttpStatus.MOVED_PERMANENTLY)
	@GetMapping("/{mappingKey}")
	public String generalAccess(@PathVariable String mappingKey) {
		log.info("=> 短链访问：{}", mappingKey);
		SlLinkMapping linkMapping = this.linkAccessService.generalAccess(mappingKey);
		return "redirect:" + linkMapping.getRedirectUrl();
	}


	/**
	 * 密码访问短链接，验证成功后302重定向到原始长链接。
	 *
	 * @param request 请求参数
	 * @return 长链接地址
	 */
	@SimpleAccessLimits({
		@SimpleAccessLimit(target = LimitTargetEnum.PASSWORD_ACCESS, level = 1, time = 5, timeUnit = TimeUnit.SECONDS, count = 3),
		@SimpleAccessLimit(target = LimitTargetEnum.PASSWORD_ACCESS, level = 2, timeUnit = TimeUnit.MINUTES, count = 15)
	})
	@ResponseBody
	@PostMapping("/password")
	public ResponseResult passwordAccess(@RequestBody PasswordAccessRequest request) {
		log.info("=> 密码访问：{}", request.getMappingKey());
		try {
			ValidationUtils.validate(request, ValidationUtils.ThrowTypeEnum.FIRST);
		} catch (Exception e) {
			throw new PasswordAccessException("访问失败：" + e.getMessage());
		}
		SlLinkMapping linkMapping = this.linkAccessService.passwordAccess(request);
		return ResponseResult.success().data(linkMapping.getLongLink());
	}

}
